#pragma once
#ifndef ELLIPSE_H
#define ELLIPSE_H

#include <stdio.h>
#include<stdint.h>
#include<stdbool.h>
#include<string.h>
#include <stdlib.h>
#include <string.h>

// 256位数据定义方便编写代码
typedef uint32_t sm2_uint256_t[8];

typedef uint32_t sm2_uint512_t[16];

// 椭圆曲线点表示，使用字节数组存储点坐标（大整数表示）。
typedef struct
{
    uint32_t x[8]; // x 坐标，32字节（256位）
    uint32_t y[8]; // y 坐标，32字节（256位）
} sm2_point_t;





// 类型转换函数
void convert_to_uint32(uint8_t src[32], uint32_t dst[8]);
void convert_to_uint8(uint32_t src[8], uint8_t dst[32]);
void sm2_getlow256(sm2_uint512_t src, sm2_uint256_t dst);
void sm2_gethigh256(sm2_uint512_t src, sm2_uint256_t dst);
void num2mgmy(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8]); // 转换为 蒙哥马利域中的数
void mgmy2num(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8]); // 将蒙哥马利域中的数转换回整数
void n_num2mgmy(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8]);
void n_mgmy2num(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8]);
void point_modp2mgmy(sm2_point_t* src, sm2_uint256_t p, sm2_point_t* dst); // 将点转换为 蒙哥马利域
void mgmy_modp2point(sm2_point_t* src, sm2_uint256_t p, sm2_point_t* dst); // 将蒙哥马利域转换为整数point

// 有限域操作函数
void neg_p(sm2_uint256_t result, const sm2_uint256_t p); // 计算2^256-p 用于溢出处理
int compare_value(sm2_uint256_t a, sm2_uint256_t b);  // 比较2个256位数的大小关系
void copy(sm2_uint256_t src, sm2_uint256_t dst); // 复制数据

uint32_t add(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t result);
uint32_t add_uint512_t(sm2_uint512_t a, sm2_uint512_t b, sm2_uint512_t result);
void mod_add(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result); // 有限域加法 (a + b) mod p
uint32_t sub(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t result);
void mod_sub(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result);   // 有限域减法 (a - b) mod p
uint32_t mul(sm2_uint256_t a, sm2_uint256_t b, sm2_uint512_t result);
void n_mod_mul(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result);
void mod_mul(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result); // 有限域乘法 (a * b) mod p
void mod_fast_exp(sm2_uint256_t a, uint32_t b, sm2_uint256_t p, sm2_uint256_t result);
void n_mod_fast_exp(sm2_uint256_t a, uint32_t b, sm2_uint256_t p, sm2_uint256_t result);
void mod_sqr(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result);     // 有限域平方 (a^2) mod p
void n_mod_sqr(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result);
void mod_inverse(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result);      // 有限域逆元 a^-1 mod p
void n_mod_inverse(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result);
bool is_zero(uint32_t* r);
bool is_in_N(uint32_t* r);
bool compare(uint8_t* r, uint8_t* k, size_t len);

// 椭圆曲线点运算函数
void point_add(const sm2_point_t* a, const sm2_point_t* b, sm2_uint256_t p, sm2_point_t* r); // 点加法 a + b= r
void point_double(const sm2_point_t* P, sm2_uint256_t p, sm2_point_t* r);                    // 点倍加 2P = R
void point_multiply(const sm2_point_t* P, const sm2_uint256_t k, sm2_uint256_t p, sm2_point_t* R);// 标量乘法 k * P = R

// 工具函数
int random_generate(sm2_uint256_t buffer);  // 默认长度为256位

// 调试和打印工具
void print_point(const sm2_point_t* P); // 打印点坐标
void print_uint32_array(uint32_t arr[8]);  // 打印uint32数组
void print_uint8_array(uint8_t arr[32]); // 打印uint8数组
void print_uint512_array(sm2_uint512_t arr); // 打印512位数据

#endif // ELLIPSE_H

